package com.example.service;

import com.example.entity.Person;
import com.example.entity.PersonRepository;
import com.example.vo.ProcessReqVO;
import com.example.vo.TaskInfo;
import com.fasterxml.jackson.core.JsonProcessingException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.flowable.bpmn.model.BpmnModel;
import org.flowable.bpmn.model.FlowNode;
import org.flowable.engine.HistoryService;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.TaskService;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.task.api.Task;
import org.flowable.task.api.TaskQuery;
import org.flowable.task.api.history.HistoricTaskInstance;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
@Service
@Transactional
public class MyService {

    @Autowired
    private RuntimeService runtimeService;

    @Autowired
    private TaskService taskService;
    //    @Autowired
//    private TaskInfoQuery taskInfoQuery;
    @Autowired
    private HistoryService historyService;

    @Autowired
    private RepositoryService repositoryService;

    @Autowired
    private PersonRepository personRepository;

    /**
     * 启动工作流
     *
     * @param assignee
     * @throws JsonProcessingException
     */
    @Transactional
    public void startProcess(String assignee) throws JsonProcessingException {
        Person person = personRepository.findByUsername(assignee);

        Map<String, Object> variables = new HashMap<String, Object>();
        variables.put("person", person);
        variables.put("taskUser", assignee);
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("oneTaskProcess", variables);
        System.out.println(processInstance.getId());
        // System.out.println(new ObjectMapper().writeValueAsString(processInstance));
    }

    /**
     * 启动工作流
     *
     * @param assignee
     * @throws JsonProcessingException
     */
    @Transactional
    public String startProcess(String assignee, String modelKey) throws JsonProcessingException {
        System.out.println(assignee);
        System.out.println(modelKey);

        Map<String, Object> variables = new HashMap<String, Object>();
        variables.put("taskUser", assignee);
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(modelKey, variables);
        System.out.println(processInstance.getId());
        return processInstance.getId();
    }

    @Transactional
    public List<Task> getTasks(String assignee) {
        return taskService.createTaskQuery().taskAssignee(assignee).list();
    }

    /**
     * 完成任务
     *
     * @param taskId
     */
    public void completeTask(String taskId) {
        taskService.complete(taskId);
        System.out.println(taskId + " complete!");
    }

    /**
     * 完成任务
     *
     * @param taskId
     */
    public void completeTask(String taskId, Map<String, Object> params) throws Exception {
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        if (task == null) {
            throw new Exception("任务不存在");
        }
        System.out.println(params);
        taskService.complete(taskId, params);
        System.out.println(taskId + " complete!");
    }

    /**
     * 退回任务
     *
     * @param taskId
     */
    public void rejectTask(String taskId, Map<String, Object> params) throws Exception {
        System.out.println(params);
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        if (task == null) {
            throw new Exception("任务不存在");
        }
        log.info(task.toString());
        String processInstanceId = task.getProcessInstanceId();
        List<HistoricTaskInstance> historyTasks = historyService.createHistoricTaskInstanceQuery().processInstanceId(processInstanceId).finished().orderByHistoricTaskInstanceEndTime().desc().list();
        if (historyTasks.isEmpty()) {
            System.out.println("没有上一步，不能退回");
            return;
        }
        HistoricTaskInstance historicTaskInstance = historyTasks.get(0);
        log.info(historicTaskInstance.toString());
        BpmnModel bpmnModel = repositoryService.getBpmnModel(task.getProcessDefinitionId());
        FlowNode lastNode = (FlowNode) bpmnModel.getFlowElement(historicTaskInstance.getTaskDefinitionKey());
        FlowNode currentNode = (FlowNode) bpmnModel.getFlowElement(task.getTaskDefinitionKey());
        log.info(lastNode.toString());
        log.info(currentNode.toString());
        // 回退操作
        runtimeService.createChangeActivityStateBuilder()
                .processInstanceId(processInstanceId)
                .moveActivityIdTo(currentNode.getId(), lastNode.getId()).changeState();
        System.out.println(taskId + " complete!");
    }

    /**
     * 转处理人
     *
     * @param taskId
     * @param newUserId
     */
    public void setAssignee(String taskId, String newUserId) {
        taskService.setAssignee(taskId, newUserId);
    }

    public void createDemoUsers() {
        if (personRepository.findAll().size() == 0) {
            personRepository.save(new Person("Fanson", "Joram", "Barrez", new Date()));
            personRepository.save(new Person("trademakers", "Tijs", "Rademakers", new Date()));
        }
    }

    /**
     * 当前处理人
     *
     * @param taskId
     */
    public void currentHandler(String taskId) {
        List<Task> tasks = taskService.createTaskQuery().taskId(taskId).list();
        // List<TaskEntityImpl> taskEntities = taskInfoQuery.taskId(taskId).list();
        log.info("taskEntities= {}", tasks);
    }

    /**
     * 当前处理人
     *
     * @param reqVO
     */
    public List<TaskInfo> currentHandler(ProcessReqVO reqVO) {
        TaskQuery taskQuery = taskService.createTaskQuery().processInstanceId(reqVO.getInstId());
        if (StringUtils.isNotBlank(reqVO.getTaskId())) {
            taskQuery.taskId(reqVO.getTaskId());
        }
        List<Task> tasks = taskQuery.list();
        log.info("tasks= {}", tasks);
        List<TaskInfo> taskInfoList = new ArrayList<>();
        if (CollectionUtils.isEmpty(tasks)) {
            return taskInfoList;
        }
        // 使用mapstruct转换
        tasks.forEach(t -> {
            TaskInfo taskInfo = new TaskInfo();
            taskInfo.setTaskId(t.getId());
            taskInfo.setUserName(t.getName());
            taskInfo.setAssignee(t.getAssignee());
            taskInfo.setInstId(t.getProcessInstanceId());
            System.out.println(t.getDelegationState().toString());
            taskInfoList.add(taskInfo);
        });
        return taskInfoList;
    }

    /**
     * 我的待办
     *
     * @param reqVO
     * @return
     */
    public List<TaskInfo> myTodoList(ProcessReqVO reqVO) {
        TaskQuery taskQuery = taskService.createTaskQuery().taskAssignee(reqVO.getUserId());
        List<Task> tasks = taskQuery.orderByTaskCreateTime().desc().list();
        log.info("tasks= {}", tasks);
        List<TaskInfo> taskInfoList = new ArrayList<>();
        if (CollectionUtils.isEmpty(tasks)) {
            return taskInfoList;
        }
        tasks.forEach(t -> {
            TaskInfo taskInfo = new TaskInfo();
            taskInfo.setTaskId(t.getId());
            taskInfo.setUserName(t.getName());
            taskInfo.setAssignee(t.getAssignee());
            taskInfo.setInstId(t.getProcessInstanceId());
            System.out.println(t.getDelegationState());
            System.out.println(t.getClaimTime());
            taskInfo.setCreateTime(t.getCreateTime());
            taskInfoList.add(taskInfo);
        });
        return taskInfoList;
    }


}